// Copyright (c) 2025. Tony Robalik.
// SPDX-License-Identifier: Apache-2.0
@file:Suppress("UnstableApiUsage")

package com.autonomousapps.tasks

import com.autonomousapps.TASK_GROUP_DEP
import com.autonomousapps.internal.AbiExclusions
import com.autonomousapps.internal.kotlin.computeAbi
import com.autonomousapps.internal.utils.bufferWriteJsonSet
import com.autonomousapps.internal.utils.filterToClassFiles
import com.autonomousapps.internal.utils.fromJson
import com.autonomousapps.internal.utils.getAndDelete
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor
import javax.inject.Inject

@CacheableTask
public abstract class AbiAnalysisTask @Inject constructor(
  private val workerExecutor: WorkerExecutor,
) : AndroidClassesTask() {

  init {
    group = TASK_GROUP_DEP
    description = "Produces a report of the ABI of this project"
  }

  /** Class files generated by any JVM source (Java, Kotlin, Groovy, etc.). May be empty. */
  @get:Classpath
  @get:InputFiles
  public abstract val classes: ConfigurableFileCollection

  @get:Optional
  @get:Input
  public abstract val exclusions: Property<String>

  @get:OutputFile
  public abstract val output: RegularFileProperty

  @get:OutputFile
  public abstract val abiDump: RegularFileProperty

  @TaskAction
  public fun action() {
    workerExecutor.noIsolation().submit(AbiAnalysisWorkAction::class.java) {
      // JVM projects
      it.classFiles.setFrom(classes.asFileTree.filterToClassFiles().files)
      // Android projects
      it.classFiles.from(androidClassFiles())

      it.exclusions.set(exclusions)
      it.output.set(output)
      it.abiDump.set(abiDump)
    }
  }

  public interface AbiAnalysisParameters : WorkParameters {
    public val classFiles: ConfigurableFileCollection
    public val exclusions: Property<String>
    public val output: RegularFileProperty
    public val abiDump: RegularFileProperty
  }

  public abstract class AbiAnalysisWorkAction : WorkAction<AbiAnalysisParameters> {

    override fun execute() {
      val output = parameters.output.getAndDelete()
      val outputAbiDump = parameters.abiDump.getAndDelete()

      val classFiles = parameters.classFiles.files
      val exclusions = parameters.exclusions.orNull?.fromJson<AbiExclusions>() ?: AbiExclusions.NONE

      val explodingAbi = computeAbi(classFiles, exclusions, outputAbiDump)

      output.bufferWriteJsonSet(explodingAbi)
    }
  }
}
